﻿using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Linq;
using System.Transactions;
using context;
using entities;

namespace DataAccessLibrary.DAL
{
    public class BookingDAO
    {
        //private const string Fail = "FAIL: ";
        //private const string Success = "SUCCESS";
        private BlueMDataContext _ctx = new BlueMDataContext();

        public bool InsertBooking(Booking booking, List<CheckIn> lstCheckIn)
        {
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, new TimeSpan(0, 0, 30)))
                {
                    List<int> roomId = lstCheckIn.Select(checkIn => checkIn.RoomID).ToList();
                    if (CheckAvailableRoom(roomId, lstCheckIn[0].CheckInDate, lstCheckIn[0].CheckOutDate))
                    {
                        //Insert Booking                
                        var lst = new EntitySet<CheckIn>();
                        foreach (CheckIn chk in lstCheckIn)
                        {
                            lst.Add(chk);
                        }
                        booking.CheckIns = lst;
                        _ctx.Bookings.InsertOnSubmit(booking);
                        _ctx.SubmitChanges();
                        scope.Complete();
                        return true;
                    }
                }
                throw new Exception("Room List Not available");
            }
            catch (Exception)
            {
                _ctx = new BlueMDataContext();
                throw;
            }
        }




        public bool UpdateBooking(Booking booking)
        {
            try
            {
                Booking bk = SelectBookingByID(booking.BookingID);
                bk.CustomerID = booking.CustomerID;
                _ctx.SubmitChanges();
                return true;
            }
            catch (Exception)
            {
                _ctx = new BlueMDataContext();
                throw;
            }
        }

        private bool CheckAvailableRoom(IEnumerable<int> roomId, DateTime inDate, DateTime outDate)
        {
            if (roomId != null)
            {
                var searchDAO = new SearchDAO();
                List<int> avaiRoomId = searchDAO.SearchRoom(inDate, outDate, 0, 0, 0, false, false, false).Select(p=>p.RoomID).ToList();
                return roomId.All(avaiRoomId.Contains);
            }
            return false;
        }

        public Booking SelectBookingByID(int pBookingID)
        {
            IQueryable<Booking> query = _ctx.Bookings;
            query = query.Where(p => p.BookingID == pBookingID);
            return query.FirstOrDefault();
        }

        public bool DeleteBooking(int bookingId)
        {
            try
            {
                Booking booking = SelectBookingByID(bookingId);
                EntitySet<CheckIn> checkIns = booking.CheckIns;
                if (checkIns.Any(c => c.CheckInEmployee != null))
                {
                    throw new Exception("Can not delete an admited booking");
                }

                foreach (var c in checkIns)
                {
                    _ctx.CheckIns.DeleteOnSubmit(c);
                }
                _ctx.Bookings.DeleteOnSubmit(booking);
                _ctx.SubmitChanges();
                return true;
            }
            catch (Exception)
            {
                _ctx = new BlueMDataContext();
                throw;
            }
        }

        public List<Booking> SelectBookingByCustomerId(int customerId)
        {
            IQueryable<Booking> queryable = _ctx.Bookings;
            queryable = queryable.Where(p => p.CheckIns.First().CheckInDate > DateTime.Today);
            queryable = queryable.Where(p => p.CustomerID == customerId);
            return queryable.ToList();
        }

        public List<Booking> SelectBookingByCustomerId(bool getAvailable, int customerId)
        {
            var today = DateTime.Now;
            IQueryable<Booking> queryable = _ctx.Bookings.Where(p => p.CustomerID == customerId);
            if (getAvailable)
            {
                queryable = queryable.Where(p => p.CheckIns.First().CheckInDate >= today);
            }
            return queryable.ToList();
        }
        
    }
}